﻿using System;
using System.Collections.Generic;
using System.Linq;

using Tszy.Unlimited.Base.Collections;
using Tszy.Unlimited.Data.AdoNet.Sql.Components.Expressions.Where;
using Tszy.Unlimited.Data.AdoNet.Sql.Descriptors;

namespace Tszy.Unlimited.Data.AdoNet.Sql.Components
{
    /// <summary>
    /// 表达式上下文。
    /// </summary>
    public class ExpressionContext
    {
        #region 构造器

        private ExpressionContext()
        {
        }

        /// <summary>
        ///
        /// </summary>
        /// <param name="entityType"></param>
        public ExpressionContext(Type entityType)
        {
            EntityType = entityType;
        }

        #endregion 构造器

        /// <summary>
        /// 唯一标识（本次查询的唯一标识）。
        /// </summary>
        public string Identity { get; set; } = string.Empty;

        /// <summary>
        /// 实体类型。
        /// </summary>
        public Type EntityType { get; set; }

        /// <summary>
        /// 参数集合。
        /// </summary>
        public MonoConcurrentDictionary<string, object> ParameterValues { get; internal set; } = new MonoConcurrentDictionary<string, object>();

        /// <summary>
        /// 条件。
        /// </summary>
        public List<WhereExpressionResult> Where { get; set; } = new List<WhereExpressionResult>();

        /// <summary>
        /// 锁。
        /// </summary>
        public bool IsLock { get; set; }

        #region count

        /// <summary>
        /// 是否存在数据。
        /// </summary>
        public bool Any { get; set; }

        /// <summary>
        /// 是否统计记录数。
        /// </summary>
        public bool Count { get; set; }

        /// <summary>
        /// Sum 统计字段。
        /// </summary>
        public IWhereMathExpressionDescriptor Sum { get; set; }

        /// <summary>
        /// AVG 求平均值。
        /// </summary>
        public IWhereMathExpressionDescriptor Average { get; set; }

        /// <summary>
        /// 求最小值。
        /// </summary>
        public IWhereMathExpressionDescriptor Min { get; set; }

        /// <summary>
        /// 求最大值。
        /// </summary>
        public IWhereMathExpressionDescriptor Max { get; set; }

        /// <summary>
        /// 返回的字段信息。
        /// </summary>
        public List<ExpressionParameter> Fields { get; set; } = new List<ExpressionParameter>();

        /// <summary>
        /// 排序。
        /// </summary>
        public Queue<ExpressionOrderByParameter> OrderBy { get; set; } = new Queue<ExpressionOrderByParameter>();

        /// <summary>
        /// 从序列的开头返回指定数量的连续元素。
        /// </summary>
        public int Take { get; set; }

        /// <summary>
        /// 跳过序列中指定数量的元素，然后返回剩余的元素。
        /// </summary>
        public int Skip { get; set; }

        #endregion count

        #region join

        ///// <summary>
        /////
        ///// </summary>
        //public string JoinTableName { get; set; }

        ///// <summary>
        ///// Join 语句。
        ///// </summary>
        //public string Join { get; set; }

        ///// <summary>
        ///// 主表是否调用过 Select 来提取字段（如果是 false 则表示没有，就需要自动补上“*”）。
        ///// </summary>
        //public bool IsMasterSelect { get; set; } = false;

        ///// <summary>
        ///// 子查询总数。
        ///// </summary>
        //public int SqlChildCount { get; set; } = 0;

        ///// <summary>
        ///// 子查询集合。
        ///// </summary>
        //public string SqlChildQuery { get; set; } = string.Empty;

        #endregion join

        #region update

        /// <summary>
        /// 使用更新语句来更新自身唯一标识来判断该数据是否是唯一。
        /// </summary>
        public bool SetUniqueProperty { get; set; }

        /// <summary>
        /// 更新并覆盖的属性列表。
        /// </summary>
        public MonoConcurrentDictionary<string, object> SetProperties { get; internal set; } = new MonoConcurrentDictionary<string, object>();

        /// <summary>
        /// 累加的属性列表。
        /// </summary>
        public MonoConcurrentDictionary<string, object> AccumulatedProperties { get; internal set; } = new MonoConcurrentDictionary<string, object>();

        #endregion update

        #region 函数

        /// <summary>
        ///
        /// </summary>
        /// <returns></returns>
        public ExpressionContext Clone()
        {
            var context = new ExpressionContext
            {
                Identity = Identity,
                //Where = Where,
                Any = Any,
                Count = Count,
                Sum = Sum,
                Average = Average,
                Min = Min,
                Max = Max,
                //Fields = Fields,
                //OrderBy = OrderBy,
                Take = Take,
                Skip = Skip,
                //SqlChildCount = SqlChildCount,
                //SqlChildQuery = SqlChildQuery ?? string.Empty,
                //Join = Join ?? string.Empty,
                //IsMasterSelect = IsMasterSelect,
                IsLock = IsLock,
                //DbTransaction = DbTransaction,
                EntityType = EntityType,
                SetUniqueProperty = SetUniqueProperty,
            };

            if (Where.Any())
            {
                foreach (var where in Where)
                {
                    context.Where.Add(where);
                }
            }

            if (Fields.Any())
            {
                foreach (var field in Fields)
                {
                    context.Fields.Add(field);
                }
            }

            if (OrderBy.Count > 0)
            {
                foreach (var orderBy in OrderBy.ToList())
                {
                    context.OrderBy.Enqueue(orderBy);
                }
            }

            if (SetProperties.Any())
            {
                foreach (var propertiey in SetProperties)
                {
                    context.SetProperties[propertiey.Key] = propertiey.Value;
                }
            }

            if (AccumulatedProperties.Any())
            {
                foreach (var propertiey in AccumulatedProperties)
                {
                    context.AccumulatedProperties[propertiey.Key] = propertiey.Value;
                }
            }

            return context;
        }

        #endregion 函数
    }

    /// <summary>
    ///
    /// </summary>
    public class ExpressionParameter
    {
        /// <summary>
        /// 属性名。
        /// </summary>
        public string Name { get; set; }

        /// <summary>
        /// 别名。
        /// </summary>
        public string Alias { get; set; }
    }

    /// <summary>
    ///
    /// </summary>
    public class ExpressionOrderByParameter
    {
        /// <summary>
        /// 属性名。
        /// </summary>
        public string Name { get; set; }

        /// <summary>
        /// 排序方式。
        /// </summary>
        public string Sort { get; set; }
    }
}